package com.bfsuol.bfsuolframework.core.controller.support;

import com.bfsuol.bfsuolframework.core.utils.DateTimeUtils;

import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * 记录页面传递过来的查询信息，其中key的含义：hql属性名!分组名_操作@类型        <br>
 * 格式：method!groupName_operation@type      <br>
 *                                                          <br>
 * 支持的操作：                                              <br>
 * 	eq = EQUAL(=)——默认，如果没有操作则为等于                 <br>
 * 	lk = LIKE(like '%keyword%')                             <br>
 *  kl= LIKE(like '%keyword')                               <br>
 *  kr= LIKE(like 'keyword%')                               <br>
 * 	gt = GREAT(>)                                           <br>
 * 	lt = LESS(<)                                            <br>
 * 	ge = GREAT_EQUAL(>=)                                    <br>
 *	le = LESS_EQUAL(<=)                                     <br>
 *	nu = IS_NULL(is null)                                   <br>
 *	ne = NOT_EQUAL(!=)                                      <br>
 *	nn = NOT_NULL(is not null)                              <br>
 *                                                          <br>
 *                                                          <br>
 * 支持的类型：                                              <br>
 * s = 字符串string：String ——默认，如果没有类型，则为字符串   <br>
 * b = 逻辑boolean：Boolean                                  <br>
 * i = 整数int：Integer                                      <br>
 * l = 长整数long：Long                                      <br>
 * f = 浮点float：Float                                      <br>
 * d = 双浮点double：Double                                  <br>
 * D = 日期date：Date(格式：yyyy-MM-dd)                      <br>
 * t = 时间datetime：Date(格式：yyyy-MM-dd hh:mm:ss)         <br>
 *                                                          <br>
 *                                                          <br>
 * 如果属性名中包含关联表，需要使用外连接查询，则建立别名，     <br>
 * 名称和别名之间使用“|”分隔，                                <br>
 * 如果使用左连接，则使用“[|”，右连接使用“|]”。               <br>
 * 例如：user.roles|r.id，则r就是user.roles的别名            <br>
 *                                                          <br>
 *                                                          <br>
 * 例如：                                                   <br>
 * user.id!eq@l=1    对应hql is : where user.id = 1        <br>
 * name!eq@s=tom     对应hql is : where name = 'tom'       <br>
 * name!lk@s=tom     对应hql is : where name like '%tom%'  <br>
 *                                                          <br>
 * user.role|r.name!eq@s=admin    对应hql is : from User u where u.role.name = 'admin'         <br>
 * 
 * 
 * @author 曹新龙
 *
 */
public interface QueryParam {

	public static enum OPERATOR {EQUAL,LIKE,LIKE_LEFT,LIKE_RIGHT,GREAT,LESS,GREAT_EQUAL,LESS_EQUAL,IS_NULL,NOT_EQUAL,NOT_NULL};
	public static enum TYPE {STRING,INTEGER,LONG,FLOAT,DOUBLE,BOOLEAN,DATE,DATETIME};
	
	public static final OPERATOR DEFAULT_OPERATOR = OPERATOR.EQUAL;
	public static final TYPE DEFAULT_TYPE = TYPE.STRING;
	
	public boolean isDistinct();
	public QueryParam setDistinct(boolean distinct);
	
	public QueryParam clear();
	/*
	 * ******************************************************************
	 * 查询
	 */
	
	public boolean hasQuerys();
	public boolean hasQuery(String key);
	public QueryParam removeQuery(String key);
	public QueryParam clearQuery();
	public QueryElement getQuery(String key);

	public Collection<String> getQueryKeys();
	public Collection<QueryElement> getQuerys();
	public Collection<QueryElement> getFixedQuerys();

	public QueryParam addQuery(String key, String value, boolean isFore);
	public QueryParam addQuery(String key, String value);
	public QueryParam addQuery(String key, Integer value);
	public QueryParam addQuery(String key, Long value);
	public QueryParam addQuery(String key, Float value);
	public QueryParam addQuery(String key, Double value);
	public QueryParam addQuery(String key, Boolean value);
	public QueryParam addQuery(String key, Date value);
	public QueryParam addQuery(String key, Date value, String pattern);

	public String getString(String key, String defaultValue);
	public Integer getInteger(String key, Integer defaultValue);
	public Long getLong(String key, Long defaultValue);
	public Float getFloat(String key, Float defaultValue);
	public Double getDouble(String key, Double defaultValue);
	public Boolean getBoolean(String key, Boolean defaultValue);
	public Date getDate(String key, Date defaultValue);
	public Date getDateTime(String key, Date defaultValue);
	public Date getDate(String key, Date defaultValue, String pattern);

	/*
	 * ***************************************************************************************************************
	 * 排序
	 */
	public Collection<OrderElement> getOrders();
	public boolean hasOrders();
	public boolean hasOrder(String order);
	public QueryParam removeOrder(String key);
	public QueryParam clearOrder();

	public QueryParam addOrder(String order);
	public QueryParam addOrderAsc(String order);
	public QueryParam addOrderDesc(String order);
	public QueryParam addOrder(String order, boolean isASC);

	/*
	 * ***********************************************************
	 * 内部类
	 */
	public class OrderElement {

		private Boolean asc = true;
		private String field = "";
		
		public OrderElement(){}
		
		public OrderElement(String field) {
			setOrder(field);
		}
		public OrderElement(String field ,boolean asc) {
			setOrder(field, asc);
		}

		public String getField() {
			return field;
		}
		public void setField(String field){
			this.field = field;
		}
		public boolean isAsc() {
			if(asc == null){
				return true;
			}
			return asc;
		}
		public void setAsc(boolean asc) {
			this.asc = asc;
		}
		public boolean reverse(){
			if(asc == null){
				asc = false;
			}else{
				setAsc(!this.asc);
			}
			return isAsc();
		}
		
		public void setOrder(String field) {
			if(field==null || field.trim().equals("")){
				return;
			}
			if(field.toLowerCase().endsWith("_asc")){
				setOrder(field.substring(0, field.length() - 4),true);
			}else if(field.toLowerCase().endsWith("_desc")){
				setOrder(field.substring(0, field.length() - 5),false);
			}else{
				setOrder(field, true);
			}
		}
		
		public void setOrder(String field,boolean asc) {
			this.field = field;
			this.asc = asc;
		}
		
		public boolean hasOrder(){
			return field!=null && !field.trim().equals("");
		}
		public String getOrder(){
			if(!hasOrder()){
				return "";
			}
			return getField() + (isAsc() ? "_asc" : "_desc");
		}
	}

	
	/*
	 * ************************************************************
	 * 内部类
	 */
	public class QueryElement{
		
		private String key;
		private String value;
		
		private String groupName = null;
		private String method = null;
		private OPERATOR operator = OPERATOR.EQUAL;
		private TYPE type = TYPE.STRING;
		private boolean is_fore = true ;
		
		private List<QueryElement> or_query = null;
		
		public QueryElement() {}
		public QueryElement(String key, String value) {
			setQuery(key,value);
		}
		
		public void setQuery(String key,String value) {
			setKey(key);
			setValue(value);
		}
		
		public void setIsfore(boolean is_fore){
			this.is_fore = is_fore;
		}
		
		private void setKey(String key){
			this.key = key;
			//查找是否含有大括号，没有则全部为method，其他都取默认值
			int pos = key.indexOf("!");
			if(pos == -1){
				method = key;
				return;
			}
			
			//处理控制字符串和method
			String str;
			method = key.substring(0,pos);
			str = key.substring(pos+1,key.length());
			
			//判断有没有or的分组
			pos = str.indexOf("_");
			if(pos >= 0){
				groupName = str.substring(0,pos);
				str = str.substring(pos+1,str.length());
			}
			//判断有没有类型
			pos = str.indexOf("@");
			if(pos >= 0){
				if(pos<str.length()-1){
					type = str2type(str.substring(pos+1,pos+2));
				}
				operator = str2operator(str.substring(0,pos));
			}else{
				operator = str2operator(str);
			}
		}
		private void setValue(String value){
			this.value = value;
		}
		
		public String getGroupName(){
			return groupName;
		}
		
		public boolean isFore(){
			return is_fore;
		}
		
		public String getKey() {
			return key;
		}
		
		public OPERATOR getOperator(){
			return operator;
		}
		
		public TYPE getType(){
			return type;
		}
		
		
		public String getMethod(){
			return method;
		}
		
		public Object getConvertedValue() {
			switch(getType()){
				case STRING:
					return getValue();
				case INTEGER:
					return getInteger(0);
				case LONG:
					return getLong(0L);
				case FLOAT:
					return getFloat(0F);
				case DOUBLE:
					return getDouble(0D);
				case BOOLEAN:
					return getBoolean(true);
				case DATE:
					return getDate(DateTimeUtils.getCurrentDateTime());
				case DATETIME:
					return getDateTime(DateTimeUtils.getCurrentDateTime());
			}
			return getValue();
		}
		
		public String getOperatorString(){
			return operator2str(operator);
		}
		
		public String getTypeString(){
			return type2str(type);
		}
		/**
		 * 返回查询值
		 * @return
		 */
		public String getValue(){
			return value;
		}
		/**
		 * 返回查询值
		 * @param defaultValue
		 * @return
		 */
		public String getString(String defaultValue){
			if(value==null || value.equals("")){
				return defaultValue;
			}
			return value;
		}
		/**
		 * 将查询值转化为整型
		 * @param defaultValue
		 * @return
		 */
		public Integer getInteger(Integer defaultValue){
			Integer v = defaultValue;
			try{
				v = Integer.valueOf(value);
			}catch(Exception e){}
			return v;
		}
		/**
		 * 将查询值转化为长整型
		 * @param defaultValue
		 * @return
		 */
		public Long getLong(Long defaultValue){
			Long v = defaultValue;
			try{
				v = Long.valueOf(value);
			}catch(Exception e){}
			return v;
		}
		/**
		 * 将查询值转化为浮点型
		 * @param defaultValue
		 * @return
		 */
		public Float getFloat(Float defaultValue){
			Float v = defaultValue;
			try{
				v = Float.valueOf(value);
			}catch(Exception e){}
			return v;
		}
		/**
		 * 将查询值转化为双浮点型
		 * @param defaultValue
		 * @return
		 */
		public Double getDouble(Double defaultValue){
			Double v = defaultValue;
			try{
				v = Double.valueOf(value);
			}catch(Exception e){}
			return v;
		}
		/**
		 * 将查询值转化为逻辑型
		 * @param defaultValue
		 * @return
		 */
		public Boolean getBoolean(Boolean defaultValue){
			Boolean v = defaultValue;
			try{
				v = Boolean.valueOf(value);
			}catch(Exception e){}
			return v;
		}
		/**
		 * 将查询值转化为日期，格式：yyyy-MM-dd
		 * @param defaultValue
		 * @return
		 */
		public Date getDate(Date defaultValue){
			return getDate(defaultValue,"yyyy-MM-dd");
		}
		/**
		 * 将查询值转化为日期，格式：yyyy-MM-dd HH:mm:ss
		 * @param defaultValue
		 * @return
		 */
		public Date getDateTime(Date defaultValue){
			return getDate(defaultValue,"yyyy-MM-dd HH:mm:ss");
		}
		/**
		 * 将查询值转化为日期
		 * @param defaultValue 默认值
		 * @param pattern 日期格式，
		 * @return
		 */
		public Date getDate(Date defaultValue,String pattern){
			Date date = defaultValue;
			if(pattern == null || pattern.equals("")){
				pattern = "yyyy-MM-dd";
			}
			try{
				date = DateTimeUtils.parse(value,pattern);
			}catch(Exception e){
				return defaultValue;
			}
			return date;
		}
		
		public Collection<QueryElement> getOrQuerys(){
			return or_query;
		}
		
		public boolean hasOrQuerys(){
			return or_query!=null && !or_query.isEmpty();
		}
		
		public void addOrQuerys(QueryElement query){
			if(or_query == null){
				or_query = new LinkedList<QueryElement>();
			}
			or_query.add(query);
		}
		
		/**
		 * 将操作转化为字符串，用于拼接queryKey
		 * @param operator
		 * @return
		 */
		private String operator2str(OPERATOR operator){
			switch(operator){
				case EQUAL:
					return "eq";
				case LIKE:
					return "lk";
				case LIKE_LEFT:
					return "kl";
				case LIKE_RIGHT:
					return "kr";
				case GREAT:
					return "gt";
				case LESS:
					return "lt";
				case GREAT_EQUAL:
					return "ge";
				case LESS_EQUAL:
					return "le";
				case IS_NULL:
					return "nu";
				case NOT_EQUAL:
					return "ne";
				case NOT_NULL:
					return "nn";
				default:
					return "eq";
			}
		}
		
		/**
		 * 将操作字符串转化为操作
		 * @param operator
		 * @return
		 */
		private OPERATOR str2operator(String operator){
			if(operator == null || operator.equals("")){
				return OPERATOR.EQUAL;
			}else if(operator.equals("lk")){
				return OPERATOR.LIKE;
			}else if(operator.equals("kl")){
				return OPERATOR.LIKE_LEFT;
			}else if(operator.equals("kr")){
				return OPERATOR.LIKE_RIGHT;
			}else if(operator.equals("gt")){
				return OPERATOR.GREAT;
			}else if(operator.equals("ge")){
				return OPERATOR.GREAT_EQUAL;
			}else if(operator.equals("lt")){
				return OPERATOR.LESS;
			}else if(operator.equals("le")){
				return OPERATOR.LESS_EQUAL;
			}else if(operator.equals("nu")){
				return OPERATOR.IS_NULL;
			}else if(operator.equals("ne")){
				return OPERATOR.NOT_EQUAL;
			}else if(operator.equals("nn")){
				return OPERATOR.NOT_NULL;
			}else{
				return OPERATOR.EQUAL;
			}
		}
		
		/**
		 * 将类型转化为字符串，用于拼接queryKey
		 * @param type
		 * @return
		 */
		private String type2str(TYPE type){
			switch(type){
				case INTEGER:
					return "i";
				case LONG:
					return "l";
				case FLOAT:
					return "f";
				case DOUBLE:
					return "d";
				case BOOLEAN:
					return "b";
				case DATE:
					return "D";
				case DATETIME:
					return "t";
				default:
					return "s";
			}
		}
		
		/**
		 * 将类型字符串转化为类型
		 * @param type
		 * @return
		 */
		private TYPE str2type(String type){
			if(type == null || type.equals("")){
				return TYPE.STRING;
			}else if(type.equals("i")){
				return TYPE.INTEGER;
			}else if(type.equals("l")){
				return TYPE.LONG;
			}else if(type.equals("f")){
				return TYPE.FLOAT;
			}else if(type.equals("d")){
				return TYPE.DOUBLE;
			}else if(type.equals("b")){
				return TYPE.BOOLEAN;
			}else if(type.equals("D")){
				return TYPE.DATE;
			}else if(type.equals("t")){
				return TYPE.DATETIME;
			}else{
				return TYPE.STRING;
			}
		}
	}


}
